import 'package:meta/meta.dart';

import '../cache.dart';

Future<CacheUpdate<T>> updatedItemIfExpired<T>(
    {@required String key, @required Cache<T> item, @required CacheUpdater<T> updater, @required bool force}) async {
  if (updater != null && (force || item == null || item.isExpired())) {
    try {
      final newCache = await updater(key);
      return UpdatedCache(item, newCache);
    }
    catch(e) {
      return FailedUpdatedCache(item, e);
    }
  }
  return NotUpdatedCache(item);
}

abstract class CacheUpdate<T> {
  final Cache<T> cache;
  CacheUpdate(this.cache);
}

class UpdatedCache<T> extends CacheUpdate<T> {
  final Cache<T> oldCache;
  UpdatedCache(this.oldCache, Cache<T> newCache) : super(newCache);
}

class NotUpdatedCache<T> extends CacheUpdate<T> {
  NotUpdatedCache(Cache<T> cache) : super(cache);
}

class FailedUpdatedCache<T> extends CacheUpdate<T> {
  final Object error;
  FailedUpdatedCache(Cache<T> cache, this.error) : super(cache);
}